/**************************************************************************//**
 * @file     main.c
 * @brief    This sample program demonstrates how to use the TSI commands to
 *           perform RSA encrypt and decrypt by modulus exponentiation operation.
 *
 * @copyright (C) 2023 Nuvoton Technology Corp. All rights reserved.
 ******************************************************************************/
#include <stdio.h>
#include <string.h>

#include "NuMicro.h"
#include "tsi_cmd.h"

#define USER_SEED       0xa7ae6d1c

struct rsa_tv_t {
	int bitlen;     /* should be 1024, 2048, 3072, or 4096 */
	u8  M[520];
	u8  N[520];
	u8  E[520];     /* public key  */
	u8  D[520];     /* private key */
} ;

struct rsa_tv_t rsa_vectors[] = {
{
	1024,

	/* M */
	"\x00\x08"
	"\x54\x85\x9b\x34\x2c\x49\xea\x2a",

	/* N - modulus */
	"\x00\x80"
	"\xBB\xF8\x2F\x09\x06\x82\xCE\x9C\x23\x38\xAC\x2B\x9D\xA8\x71\xF7"
	"\x36\x8D\x07\xEE\xD4\x10\x43\xA4\x40\xD6\xB6\xF0\x74\x54\xF5\x1F"
	"\xB8\xDF\xBA\xAF\x03\x5C\x02\xAB\x61\xEA\x48\xCE\xEB\x6F\xCD\x48"
	"\x76\xED\x52\x0D\x60\xE1\xEC\x46\x19\x71\x9D\x8A\x5B\x8B\x80\x7F"
	"\xAF\xB8\xE0\xA3\xDF\xC7\x37\x72\x3E\xE6\xB4\xB7\xD9\x3A\x25\x84"
	"\xEE\x6A\x64\x9D\x06\x09\x53\x74\x88\x34\xB2\x45\x45\x98\x39\x4E"
	"\xE0\xAA\xB1\x2D\x7B\x61\xA5\x1F\x52\x7A\x9A\x41\xF6\xC1\x68\x7F"
	"\xE2\x53\x72\x98\xCA\x2A\x8F\x59\x46\xF8\xE5\xFD\x09\x1D\xBD\xCB",

	/* E - public key */
	"\x00\x01"
	"\x11",

	/* D - private key */
	"\x00\x80"
	"\xA5\xDA\xFC\x53\x41\xFA\xF2\x89\xC4\xB9\x88\xDB\x30\xC1\xCD\xF8"
	"\x3F\x31\x25\x1E\x06\x68\xB4\x27\x84\x81\x38\x01\x57\x96\x41\xB2"
	"\x94\x10\xB3\xC7\x99\x8D\x6B\xC4\x65\x74\x5E\x5C\x39\x26\x69\xD6"
	"\x87\x0D\xA2\xC0\x82\xA9\x39\xE3\x7F\xDC\xB8\x2E\xC9\x3E\xDA\xC9"
	"\x7F\xF3\xAD\x59\x50\xAC\xCF\xBC\x11\x1C\x76\xF1\xA9\x52\x94\x44"
	"\xE5\x6A\xAF\x68\xC5\x6C\x09\x2C\xD3\x8D\xC3\xBE\xF5\xD2\x0A\x93"
	"\x99\x26\xED\x4F\x74\xA1\x3E\xDD\xFB\xE1\xA1\xCE\xCC\x48\x94\xAF"
	"\x94\x28\xC2\xB7\xB8\x88\x3F\xE4\x46\x3A\x4B\xC8\x5B\x1C\xB3\xC1",
},
{
	1024,

	/* M */
	"\x00\x08"
	"\x54\x85\x9b\x34\x2c\x49\xea\x2a",

	/* N - modulus */
	"\x00\x80"
	"\xBB\xF8\x2F\x09\x06\x82\xCE\x9C\x23\x38\xAC\x2B\x9D\xA8\x71\xF7"
	"\x36\x8D\x07\xEE\xD4\x10\x43\xA4\x40\xD6\xB6\xF0\x74\x54\xF5\x1F"
	"\xB8\xDF\xBA\xAF\x03\x5C\x02\xAB\x61\xEA\x48\xCE\xEB\x6F\xCD\x48"
	"\x76\xED\x52\x0D\x60\xE1\xEC\x46\x19\x71\x9D\x8A\x5B\x8B\x80\x7F"
	"\xAF\xB8\xE0\xA3\xDF\xC7\x37\x72\x3E\xE6\xB4\xB7\xD9\x3A\x25\x84"
	"\xEE\x6A\x64\x9D\x06\x09\x53\x74\x88\x34\xB2\x45\x45\x98\x39\x4E"
	"\xE0\xAA\xB1\x2D\x7B\x61\xA5\x1F\x52\x7A\x9A\x41\xF6\xC1\x68\x7F"
	"\xE2\x53\x72\x98\xCA\x2A\x8F\x59\x46\xF8\xE5\xFD\x09\x1D\xBD\xCB",

	/* E - public key */
	"\x00\x01"
	"\x11",

	/* D - private key */
	"\x00\x80"
	"\xA5\xDA\xFC\x53\x41\xFA\xF2\x89\xC4\xB9\x88\xDB\x30\xC1\xCD\xF8"
	"\x3F\x31\x25\x1E\x06\x68\xB4\x27\x84\x81\x38\x01\x57\x96\x41\xB2"
	"\x94\x10\xB3\xC7\x99\x8D\x6B\xC4\x65\x74\x5E\x5C\x39\x26\x69\xD6"
	"\x87\x0D\xA2\xC0\x82\xA9\x39\xE3\x7F\xDC\xB8\x2E\xC9\x3E\xDA\xC9"
	"\x7F\xF3\xAD\x59\x50\xAC\xCF\xBC\x11\x1C\x76\xF1\xA9\x52\x94\x44"
	"\xE5\x6A\xAF\x68\xC5\x6C\x09\x2C\xD3\x8D\xC3\xBE\xF5\xD2\x0A\x93"
	"\x99\x26\xED\x4F\x74\xA1\x3E\xDD\xFB\xE1\xA1\xCE\xCC\x48\x94\xAF"
	"\x94\x28\xC2\xB7\xB8\x88\x3F\xE4\x46\x3A\x4B\xC8\x5B\x1C\xB3\xC1",
},
{
	2048,

	/* M */
	"\x00\x08"
	"\x54\x85\x9b\x34\x2c\x49\xea\x2a",

	/* N - modulus */
	"\x01\x00"
	"\xDB\x10\x1A\xC2\xA3\xF1\xDC\xFF\x13\x6B\xED\x44\xDF\xF0\x02\x6D"
	"\x13\xC7\x88\xDA\x70\x6B\x54\xF1\xE8\x27\xDC\xC3\x0F\x99\x6A\xFA"
	"\xC6\x67\xFF\x1D\x1E\x3C\x1D\xC1\xB5\x5F\x6C\xC0\xB2\x07\x3A\x6D"
	"\x41\xE4\x25\x99\xAC\xFC\xD2\x0F\x02\xD3\xD1\x54\x06\x1A\x51\x77"
	"\xBD\xB6\xBF\xEA\xA7\x5C\x06\xA9\x5D\x69\x84\x45\xD7\xF5\x05\xBA"
	"\x47\xF0\x1B\xD7\x2B\x24\xEC\xCB\x9B\x1B\x10\x8D\x81\xA0\xBE\xB1"
	"\x8C\x33\xE4\x36\xB8\x43\xEB\x19\x2A\x81\x8D\xDE\x81\x0A\x99\x48"
	"\xB6\xF6\xBC\xCD\x49\x34\x3A\x8F\x26\x94\xE3\x28\x82\x1A\x7C\x8F"
	"\x59\x9F\x45\xE8\x5D\x1A\x45\x76\x04\x56\x05\xA1\xD0\x1B\x8C\x77"
	"\x6D\xAF\x53\xFA\x71\xE2\x67\xE0\x9A\xFE\x03\xA9\x85\xD2\xC9\xAA"
	"\xBA\x2A\xBC\xF4\xA0\x08\xF5\x13\x98\x13\x5D\xF0\xD9\x33\x34\x2A"
	"\x61\xC3\x89\x55\xF0\xAE\x1A\x9C\x22\xEE\x19\x05\x8D\x32\xFE\xEC"
	"\x9C\x84\xBA\xB7\xF9\x6C\x3A\x4F\x07\xFC\x45\xEB\x12\xE5\x7B\xFD"
	"\x55\xE6\x29\x69\xD1\xC2\xE8\xB9\x78\x59\xF6\x79\x10\xC6\x4E\xEB"
	"\x6A\x5E\xB9\x9A\xC7\xC4\x5B\x63\xDA\xA3\x3F\x5E\x92\x7A\x81\x5E"
	"\xD6\xB0\xE2\x62\x8F\x74\x26\xC2\x0C\xD3\x9A\x17\x47\xE6\x8E\xAB",

	/* E - public key */
	"\x00\x03"
	"\x01\x00\x01",

	/* D - private key */
	"\x01\x00"
	"\x52\x41\xF4\xDA\x7B\xB7\x59\x55\xCA\xD4\x2F\x0F\x3A\xCB\xA4\x0D"
	"\x93\x6C\xCC\x9D\xC1\xB2\xFB\xFD\xAE\x40\x31\xAC\x69\x52\x21\x92"
	"\xB3\x27\xDF\xEA\xEE\x2C\x82\xBB\xF7\x40\x32\xD5\x14\xC4\x94\x12"
	"\xEC\xB8\x1F\xCA\x59\xE3\xC1\x78\xF3\x85\xD8\x47\xA5\xD7\x02\x1A"
	"\x65\x79\x97\x0D\x24\xF4\xF0\x67\x6E\x75\x2D\xBF\x10\x3D\xA8\x7D"
	"\xEF\x7F\x60\xE4\xE6\x05\x82\x89\x5D\xDF\xC6\xD2\x6C\x07\x91\x33"
	"\x98\x42\xF0\x02\x00\x25\x38\xC5\x85\x69\x8A\x7D\x2F\x95\x6C\x43"
	"\x9A\xB8\x81\xE2\xD0\x07\x35\xAA\x05\x41\xC9\x1E\xAF\xE4\x04\x3B"
	"\x19\xB8\x73\xA2\xAC\x4B\x1E\x66\x48\xD8\x72\x1F\xAC\xF6\xCB\xBC"
	"\x90\x09\xCA\xEC\x0C\xDC\xF9\x2C\xD7\xEB\xAE\xA3\xA4\x47\xD7\x33"
	"\x2F\x8A\xCA\xBC\x5E\xF0\x77\xE4\x97\x98\x97\xC7\x10\x91\x7D\x2A"
	"\xA6\xFF\x46\x83\x97\xDE\xE9\xE2\x17\x03\x06\x14\xE2\xD7\xB1\x1D"
	"\x77\xAF\x51\x27\x5B\x5E\x69\xB8\x81\xE6\x11\xC5\x43\x23\x81\x04"
	"\x62\xFF\xE9\x46\xB8\xD8\x44\xDB\xA5\xCC\x31\x54\x34\xCE\x3E\x82"
	"\xD6\xBF\x7A\x0B\x64\x21\x6D\x88\x7E\x5B\x45\x12\x1E\x63\x8D\x49"
	"\xA7\x1D\xD9\x1E\x06\xCD\xE8\xBA\x2C\x8C\x69\x32\xEA\xBE\x60\x71",
},
{
	3072,

	/* M */
	"\x00\x40"
	"\x65\x79\x97\x0D\x24\xF4\xF0\x67\x6E\x75\x2D\xBF\x10\x3D\xA8\x7D"
	"\xEF\x7F\x60\xE4\xE6\x05\x82\x89\x5D\xDF\xC6\xD2\x6C\x07\x91\x33"
	"\x98\x42\xF0\x02\x00\x25\x38\xC5\x85\x69\x8A\x7D\x2F\x95\x6C\x43"
	"\x9A\xB8\x81\xE2\xD0\x07\x35\xAA\x05\x41\xC9\x1E\xAF\xE4\x04\x3B"
	"\x19\xB8\x73\xA2\xAC\x4B\x1E\x66\x48\xD8\x72\x1F\xAC\xF6\xCB\xBC",

	/* N - modulus */
	"\x01\x80"
	"\xb6\x59\x34\x31\x9c\x20\x60\x1d\x5f\xec\xf0\x3b\xd2\xe4\xc0\xa3"
	"\x1d\xfa\xe9\xae\x73\x1a\x7c\x41\x5b\xab\xa1\xe8\x22\x8f\x16\xff"
	"\x11\xcf\x8e\xeb\x59\x4c\xe1\x13\x81\x36\x54\xb0\xef\xd9\xd2\x82"
	"\xde\x4a\x52\xb2\xec\xbc\x20\x70\xb9\x96\x80\x94\xeb\x99\xc6\xcc"
	"\x2a\x4d\x40\xcc\x47\x7b\xa2\xd1\xc3\x24\x9c\xb6\x1d\x2e\xd1\xa9"
	"\xbd\xf2\xaa\xf0\x13\x60\x3c\xda\x49\xeb\xe8\x0c\x0a\x35\x83\x33"
	"\xf0\xda\x6d\xab\xff\xb1\x3b\x74\x39\x20\x76\x56\xf8\x89\x4a\xad"
	"\x7c\xc6\xb6\xb4\xc1\x22\xf9\x35\x5a\x62\x99\x62\x50\x4e\xea\xe3"
	"\x17\xb2\xbb\xa8\xa1\x10\x58\x2f\x95\x5a\xa6\xf4\xc4\x1c\x0b\x31"
	"\x1e\x88\x0a\xc8\x2a\xd0\x48\xb0\x85\xf1\x99\x7d\x34\x3a\x99\x54"
	"\xc6\x0d\xb6\xf0\x6a\xa0\x58\x69\x79\xad\x9c\x42\xcc\x86\x00\x3a"
	"\x40\x4a\x38\x6c\xff\x8c\x1f\x8a\x64\x4a\x8a\x4d\x36\x9a\xbc\x8d"
	"\xf4\x67\x0b\x7d\x20\xdc\x88\xd9\x85\x6a\x02\xa1\x88\x21\x68\xe1"
	"\xbc\x41\xb2\xc0\xaf\x09\xdc\x90\x6c\xfa\xc6\x2b\xf6\xca\x04\x35"
	"\x32\xc8\x38\x57\xaf\x26\xd5\xbe\x46\x84\xa2\xe7\x02\x5f\x47\xfe"
	"\x52\x46\x97\x4d\x28\xb5\xed\x7c\xd1\xab\xa8\x01\xc2\x7f\x8a\x34"
	"\x48\x91\x56\xe4\x0d\x81\xe3\xed\xeb\x52\x8a\xe4\x3e\x1d\x44\x6c"
	"\xae\xec\x20\xa5\xd1\x84\x1c\xc9\x9c\x85\x41\xd1\x4d\x28\x2b\x56"
	"\xd4\xa4\x3b\xcf\xfa\xf7\x42\x8e\x8c\x7d\xf4\x38\xc4\x8f\x70\x38"
	"\x43\xfd\x47\xaf\x29\x6d\xec\x9f\xed\xdc\x1a\xb2\xa5\xbd\xd5\x47"
	"\x83\x46\x73\xef\xe7\x5a\x07\xf0\x4b\xcd\xdf\x2b\x30\x9a\x88\x45"
	"\xbc\xbb\xde\x15\x22\xac\x27\xe0\x7a\x47\x0b\xb3\xaf\x2e\xaa\x08"
	"\xe5\x6e\x91\xbe\xbb\x7a\x9e\x78\xca\x7f\xf3\x07\xb6\xfb\xad\x11"
	"\x77\x04\x1c\xd5\x2d\xb1\x36\x3a\xa9\xf9\x54\xa0\xe2\x95\x15\x53",

	/* E - public key */
	"\x00\x01"
	"\x11",

	/* D - private key */
	"\x01\x80"
	"\x10\x16\xee\x04\x60\x99\x71\xe4\x79\x67\xba\xd8\x1a\x23\x3e\x2c"
	"\x82\xa5\x32\xbc\x91\xaf\x83\x6f\x2d\xbc\x52\x0c\xf3\xfd\x91\x16"
	"\x81\x92\x50\x60\x0f\x68\xaa\x72\xa9\x84\xcb\x3c\xc9\xde\x83\x84"
	"\x04\x8e\x16\x5b\x14\xe3\x6c\x46\x2e\x7e\x38\x85\x9c\x51\x55\x4e"
	"\x3f\xf7\xc1\xf3\xe8\x30\x8e\x5d\xcd\x74\x2b\xf1\xf3\x84\x21\x8e"
	"\xfa\x2c\x00\x06\x1f\xd3\xc9\x22\x51\xd1\x0c\xf2\x00\xe6\x9a\xa2"
	"\xb3\x5e\x91\x34\xd2\xcb\xdf\x99\x50\x55\xb0\x16\xbb\x93\xa4\xb4"
	"\xf4\x6b\xe2\xf1\xd4\xce\x61\x48\x78\xea\x95\x10\x34\x43\x32\xd7"
	"\xcd\x62\x98\x16\x68\x90\x80\x40\x6f\x0f\x87\x33\xb6\xf3\x6a\x66"
	"\x37\x66\x5b\x4d\xe5\xa8\xf7\x5a\xde\xa4\x60\x5d\xde\xf6\x1c\x96"
	"\x89\xf2\x26\xba\xdc\x3b\x53\x18\x5d\x8f\x51\x8d\x6c\x66\x2d\x32"
	"\x50\xf7\x7d\x73\x07\x7d\x4e\x13\xbd\x8e\x1b\x43\x0c\x58\xf2\x84"
	"\xd8\xd1\x97\x57\xd5\x2b\x6f\x4c\xcf\x83\x3c\xe0\x33\x7c\xde\x89"
	"\x69\xdc\x75\x47\xfe\xea\x67\xdd\xb0\x5e\x41\x93\xf4\x9f\x41\x19"
	"\x0b\x39\xf5\xd8\xc7\x8a\xcd\xfd\x19\x18\x6c\xda\xa5\xc9\x58\xef"
	"\xb1\xd5\x18\x75\x01\xd5\x98\x96\x0d\xe6\x27\x5c\x64\xcc\xc5\x19"
	"\x1e\x03\x3f\xcc\x0a\x5a\x57\x72\x46\xba\x55\xd1\x95\x7e\x67\xd0"
	"\x9e\x18\x5c\xa6\x54\x0b\x52\x83\x20\xd2\xfc\xcd\x7d\x11\x51\xe6"
	"\xfc\xe4\xe2\x60\x31\xe3\xc4\xed\x83\xc1\x0b\x2e\xd5\x8e\xfd\x6a"
	"\xe9\x35\x7c\xe9\xfc\xa7\x11\x9b\x3a\x04\x54\xe3\x24\x0f\x9a\x39"
	"\x05\xb5\x7f\x9a\x96\xa8\x6a\xab\xfb\xca\xc1\x63\x59\x0d\x0b\xa7"
	"\x0e\xdd\x92\xb9\xdf\xc2\x49\x5c\x8b\x23\x33\x54\xda\x62\x18\xf9"
	"\xe6\x71\xc2\x7f\xc1\x92\x57\xa1\x3e\xa8\xf2\xbb\x9a\x21\x98\xc2"
	"\xa3\xfe\x40\x11\x4b\x66\xd9\x81\x83\x2b\xab\x2d\x8a\xc5\x10\xdd",
},
{
	4096,

	/* M */
	"\x00\x08"
	"\x54\x85\x9b\x34\x2c\x49\xea\x2a",

	/* N - modulus */
	"\x02\x00"
	"\xC3\x8B\x55\x7B\x73\x4D\xFF\xE9\x9B\xC6\xDC\x67\x3C\xB4\x8E\xA0"
	"\x86\xED\xF2\xB9\x50\x5C\x54\x5C\xBA\xE4\xA1\xB2\xA7\xAE\x2F\x1B"
	"\x7D\xF1\xFB\xAC\x79\xC5\xDF\x1A\x00\xC9\xB2\xC1\x61\x25\x33\xE6"
	"\x9C\xE9\xCF\xD6\x27\xC4\x4E\x44\x30\x44\x5E\x08\xA1\x87\x52\xCC"
	"\x6B\x97\x70\x8C\xBC\xA5\x06\x31\x0C\xD4\x2F\xD5\x7D\x26\x24\xA2"
	"\xE2\xAC\x78\xF4\x53\x14\xCE\xF7\x19\x2E\xD7\xF7\xE6\x0C\xB9\x56"
	"\x7F\x0B\xF1\xB1\xE2\x43\x70\xBD\x86\x1D\xA1\xCC\x2B\x19\x08\x76"
	"\xEF\x91\xAC\xBF\x20\x24\x0D\x38\xC0\x89\xB8\x9A\x70\xB3\x64\xD9"
	"\x8F\x80\x41\x10\x5B\x9F\xB1\xCB\x76\x43\x00\x21\x25\x36\xD4\x19"
	"\xFC\x55\x95\x10\xE4\x26\x74\x98\x2C\xD9\xBD\x0B\x2B\x04\xC2\xAC"
	"\x82\x38\xB4\xDD\x4C\x04\x7E\x51\x36\x40\x1E\x0B\xC4\x7C\x25\xDD"
	"\x4B\xB2\xE7\x20\x0A\x57\xF9\xB4\x94\xC3\x08\x33\x22\x6F\x8B\x48"
	"\xDB\x03\x68\x5A\x5B\xBA\xAE\xF3\xAD\xCF\xC3\x6D\xBA\xF1\x28\x67"
	"\x7E\x6C\x79\x07\xDE\xFC\xED\xE7\x96\xE3\x6C\xE0\x2C\x87\xF8\x02"
	"\x01\x28\x38\x43\x21\x53\x84\x69\x75\x78\x15\x7E\xEE\xD2\x1B\xB9"
	"\x23\x40\xA8\x86\x1E\x38\x83\xB2\x73\x1D\x53\xFB\x9E\x2A\x8A\xB2"
	"\x75\x35\x01\xC3\xC3\xC4\x94\xE8\x84\x86\x64\x81\xF4\x42\xAA\x3C"
	"\x0E\xD6\x4F\xBC\x0A\x09\x2D\xE7\x1B\xD4\x10\xA8\x54\xEA\x89\x84"
	"\x8A\xCB\xF7\x5A\x3C\xCA\x76\x08\x29\x62\xB4\x6A\x22\xDF\x14\x95"
	"\x71\xFD\xB6\x86\x39\xB8\x8B\xF8\x91\x7F\x38\xAA\x14\xCD\xE5\xF5"
	"\x1D\xC2\x6D\x53\x69\x52\x84\x7F\xA3\x1A\x5E\x26\x04\x83\x06\x73"
	"\x52\x56\xCF\x76\x26\xC9\xDD\x75\xD7\xFC\xF4\x69\xD8\x7B\x55\xB7"
	"\x68\x13\x53\xB9\xE7\x89\xC3\xE8\xD6\x6E\xA7\x6D\xEA\x81\xFD\xC4"
	"\xB7\x05\x5A\xB7\x41\x0A\x23\x8E\x03\x8A\x1C\xAE\xD3\x1E\xCE\xE3"
	"\x5E\xFC\x19\x4A\xEE\x61\x9B\x8E\xE5\xE5\xDD\x85\xF9\x41\xEC\x14"
	"\x53\x92\xF7\xDD\x06\x85\x02\x91\xE3\xEB\x6C\x43\x03\xB1\x36\x7B"
	"\x89\x5A\xA8\xEB\xFC\xD5\xA8\x35\xDC\x81\xD9\x5C\xBD\xCA\xDC\x9B"
	"\x98\x0B\x06\x5D\x0C\x5B\xEE\xF3\xD5\xCC\x57\xC9\x71\x2F\x90\x3B"
	"\x3C\xF0\x8E\x4E\x35\x48\xAE\x63\x74\xA9\xFC\x72\x75\x8E\x34\xA8"
	"\xF2\x1F\xEA\xDF\x3A\x37\x2D\xE5\x39\x39\xF8\x57\x58\x3C\x04\xFE"
	"\x87\x06\x98\xBC\x7B\xD3\x21\x36\x60\x25\x54\xA7\x3D\xFA\x91\xCC"
	"\xA8\x0B\x92\x8E\xB4\xF7\x06\xFF\x1E\x95\xCB\x07\x76\x97\x3B\x9D",

	/* E - public key */
	"\x00\x03"
	"\x01\x00\x01",

	/* D - private key */
	"\x02\x00"
	"\x74\xA9\xE0\x6A\x32\xB4\xCA\x85\xD9\x86\x9F\x60\x88\x7B\x40\xCC"
	"\xCD\x33\x91\xA8\xB6\x25\x1F\xBF\xE3\x51\x1C\x97\xB6\x2A\xD9\xB8"
	"\x11\x40\x19\xE3\x21\x13\xC8\xB3\x7E\xDC\xD7\x65\x40\x4C\x2D\xD6"
	"\xDC\xAF\x32\x6C\x96\x75\x2C\x2C\xCA\x8F\x3F\x7A\xEE\xC4\x09\xC6"
	"\x24\x3A\xC9\xCF\x6D\x8D\x17\x50\x94\x52\xD3\xE7\x0F\x2F\x7E\x94"
	"\x1F\xA0\xBE\xD9\x25\xE8\x38\x42\x7C\x27\xD2\x79\xF8\x2A\x87\x38"
	"\xEF\xBB\x74\x8B\xA8\x6E\x8C\x08\xC6\xC7\x4F\x0C\xBC\x79\xC6\xEF"
	"\x0E\xA7\x5E\xE4\xF8\x8C\x09\xC7\x5E\x37\xCC\x87\x77\xCD\xCF\xD1"
	"\x6D\x28\x1B\xA9\x62\xC0\xB8\x16\xA7\x8B\xF9\xBB\xCC\xB4\x15\x7F"
	"\x1B\x69\x03\xF2\x7B\xEB\xE5\x8C\x14\xD6\x23\x4F\x52\x6F\x18\xA6"
	"\x4B\x5B\x01\xAD\x35\xF9\x48\x53\xB3\x86\x35\x66\xD7\xE7\x29\xC0"
	"\x09\xB5\xC6\xE6\xFA\xC4\xDA\x19\xBE\xD7\x4D\x41\x14\xBE\x6F\xDF"
	"\x1B\xAB\xC0\xCA\x88\x07\xAC\xF1\x7D\x35\x83\x67\x28\x2D\x50\xE9"
	"\xCE\x27\x71\x5E\x1C\xCF\xD2\x30\x65\x79\x72\x2F\x9C\xE1\xD2\x39"
	"\x7F\xEF\x3B\x01\xF2\x14\x1D\xDF\xBD\x51\xD3\xA1\x53\x62\xCF\x5F"
	"\x79\x84\xCE\x06\x96\x69\x29\x49\x82\x1C\x71\x4A\xA1\x66\xC8\x2F"
	"\xFD\x7B\x96\x7B\xFC\xC4\x26\x58\xC4\xFC\x7C\xAF\xB5\xE8\x95\x83"
	"\x87\xCB\x46\xDE\x97\xA7\xB3\xA2\x54\x5B\xD7\xAF\xAB\xEB\xC8\xF3"
	"\x55\x9D\x48\x2B\x30\x9C\xDC\x26\x4B\xC2\x89\x45\x13\xB2\x01\x9A"
	"\xA4\x65\xC3\xEC\x24\x2D\x26\x97\xEB\x80\x8A\x9D\x03\xBC\x59\x66"
	"\x9E\xE2\xBB\xBB\x63\x19\x64\x93\x11\x7B\x25\x65\x30\xCD\x5B\x4B"
	"\x2C\xFF\xDC\x2D\x30\x87\x1F\x3C\x88\x07\xD0\xFC\x48\xCC\x05\x8A"
	"\xA2\xC8\x39\x3E\xD5\x51\xBC\x0A\xBE\x6D\xA8\xA0\xF6\x88\x06\x79"
	"\x13\xFF\x1B\x45\xDA\x54\xC9\x24\x25\x8A\x75\x0A\x26\xD1\x69\x81"
	"\x14\x14\xD1\x79\x7D\x8E\x76\xF2\xE0\xEB\xDD\x0F\xDE\xC2\xEC\x80"
	"\xD7\xDC\x16\x99\x92\xBE\xCB\x40\x0C\xCE\x7C\x3B\x46\xA2\x5B\x5D"
	"\x0C\x45\xEB\xE1\x00\xDE\x72\x50\xB1\xA6\x0B\x76\xC5\x8D\xFC\x82"
	"\x38\x6D\x99\x14\x1D\x1A\x4A\xD3\x7C\x53\xB8\x12\x46\xA2\x30\x38"
	"\x82\xF4\x96\x6E\x8C\xCE\x47\x0D\xAF\x0A\x3B\x45\xB7\x43\x95\x43"
	"\x9E\x02\x2C\x44\x07\x6D\x1F\x3C\x66\x89\x09\xB6\x1F\x06\x30\xCC"
	"\xAD\xCE\x7D\x9A\xDE\x3E\xFB\x6C\xE4\x58\x43\xD2\x4F\xA5\x9E\x5E"
	"\xA7\x7B\xAE\x3A\xF6\x7E\xD9\xDB\xD3\xF5\xC5\x41\xAF\xE6\x9C\x91",
},
};

static uint32_t  g_param_mem[1600 * 4] __attribute__((aligned(32)));
static uint32_t  g_output_mem[130 * 4] __attribute__((aligned(32)));


static char  hex_char_tbl[] = "0123456789abcdef";

void  print_data(char *str, uint8_t *buff, int len)
{
	int  i;

	sysprintf("%s: ", str);
	for (i = 0; i < len; i++)
		sysprintf("%02x", buff[i]);
	sysprintf("\n");
}

void SYS_Init(void)
{
	/* Enable UART module clock */
	CLK_EnableModuleClock(UART0_MODULE);

	/* Select UART module clock source as SYSCLK1 and UART module clock divider as 15 */
	CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL2_UART0SEL_SYSCLK1_DIV2, CLK_CLKDIV1_UART0(15));

	/* enable Wormhole 1 clock */
	CLK_EnableModuleClock(WH1_MODULE);

	/* Set GPE multi-function pins for UART0 RXD and TXD */
	SYS->GPE_MFPH &= ~(SYS_GPE_MFPH_PE14MFP_Msk | SYS_GPE_MFPH_PE15MFP_Msk);
	SYS->GPE_MFPH |= (SYS_GPE_MFPH_PE14MFP_UART0_TXD | SYS_GPE_MFPH_PE15MFP_UART0_RXD);
}

void UART0_Init()
{
	/* Configure UART0 and set UART0 baud rate */
	UART_Open(UART0, 115200);
}

static int rsa_hex_to_reg(uint8_t *input, int keylen, int rsa_bit_len, uint32_t *reg)
{
	int rsa_byte_len = rsa_bit_len / 8;
	uint8_t *key;
	int idx;
	uint8_t buff[512];

	memset(buff, 0, sizeof(buff));

	/* remove leading 0x00's */
	for (key = input; ((*key == 0x00) && (keylen > 0)); key++)
		keylen--;

	if (keylen > rsa_byte_len)
		return -1;

	memcpy(&buff[rsa_byte_len - keylen], key, keylen);

	for (idx = rsa_byte_len - 1; idx > 0; idx -= 4) {
		*reg++ = (buff[idx - 3] << 24) | (buff[idx - 2] << 16) |
				(buff[idx - 1] << 8) | buff[idx];
	}
	return 0;
}

static void rsa_reg_to_hex(uint32_t *reg, int rsa_bit_len, uint8_t *key, int *key_sz)
{
	int i, idx;

	*key_sz = 0;
	for (idx = rsa_bit_len / 32 - 1 ; idx >= 0; idx--)
	{
		for (i = 3; i >= 0; i--)
		{
			*key++ = (reg[idx] >> (i*8)) & 0xff;
			(*key_sz)++;
			if (*key_sz >= 512)
				return;
		}
	}
}

static int rsa_set_parameter(int rsa_bit_len, uint8_t *dst_buff, uint8_t *kbuf)
{
	int   keylen;

	keylen = (kbuf[0] << 8) | kbuf[1];
	if (keylen > 512)
		return -1;
	memset(dst_buff, 0, 512);
	return rsa_hex_to_reg(&kbuf[2], keylen, rsa_bit_len, (uint32_t *)dst_buff);
}

int32_t main(void)
{
	uint8_t *param = nc_ptr(g_param_mem);
	uint8_t *output = nc_ptr(g_output_mem);
	int i, klen, ret;
	int rsa_bit_len, rsa_len;
	uint8_t  out_text[514];

	/* Unlock protected registers */
	SYS_UnlockReg();

	/* Init System, IP clock and multi-function I/O */
	SYS_Init();

	/* Init UART0 for sysprintf */
	UART0_Init();

	if (TSI_Init() != 0)
	{
		sysprintf("TSI Init failed!\n");
		while (1);
	}

	sysprintf("\n\n+---------------------------------------+\n");
	sysprintf("|  MA35D1 RSA encrypt and decrypt       |\n");
	sysprintf("+---------------------------------------+\n");

	for (i = 0; i < sizeof(rsa_vectors)/sizeof(struct rsa_tv_t); i++) {
		sysprintf("\n\nRun test vector RSA-%d encrypt\n", rsa_vectors[i].bitlen);

		klen = (rsa_vectors[i].M[0] << 8) | rsa_vectors[i].M[1];
		print_data("RSA input: ", (uint8_t *)&(rsa_vectors[i].M[2]), klen);

		memset(param, 0, 1538 * 4);
		memset(output, 0, 128 * 4);
		rsa_bit_len = rsa_vectors[i].bitlen;
		rsa_len = (rsa_bit_len - 1) / 1024;

		rsa_set_parameter(rsa_bit_len, &param[0], rsa_vectors[i].M);
		rsa_set_parameter(rsa_bit_len, &param[128 * 4], rsa_vectors[i].N);
		rsa_set_parameter(rsa_bit_len, &param[256 * 4], rsa_vectors[i].E);

		ret = TSI_RSA_Exp_Mod(rsa_len, 0, RSA_KEY_SEL_USER, 0, ptr_to_u32(param), ptr_to_u32(output));
		if (ret != 0)
			goto err_out;

		memset(out_text, 0, sizeof(out_text));
		rsa_reg_to_hex((uint32_t *)output, rsa_bit_len, &out_text[2], &klen);
		out_text[0] = (klen >> 8) & 0xff;
		out_text[1] = klen & 0xff;
		print_data("RSA Encrypt output: ", &out_text[2], rsa_bit_len / 8);

		memset(param, 0, 1538 * 4);
		memset(output, 0, 128 * 4);

		rsa_set_parameter(rsa_bit_len, &param[0], out_text);
		rsa_set_parameter(rsa_bit_len, &param[128 * 4], rsa_vectors[i].N);
		rsa_set_parameter(rsa_bit_len, &param[256 * 4], rsa_vectors[i].D);

		ret = TSI_RSA_Exp_Mod(rsa_len, 0, RSA_KEY_SEL_USER, 0, ptr_to_u32(param), ptr_to_u32(output));
		if (ret != 0)
			goto err_out;

		memset(out_text, 0, sizeof(out_text));
		rsa_reg_to_hex((uint32_t *)output, rsa_bit_len, &out_text[2], &klen);
		out_text[0] = (klen >> 8) & 0xff;
		out_text[1] = klen & 0xff;
		print_data("RSA Decrypt output: ", &out_text[2], rsa_bit_len / 8);
	}
	sysprintf("\nRSA encrypt and decrypt done.\n");
	while (1);

err_out:
	sysprintf("Failed!!\n");
	TSI_Print_Error(ret);
	while (1);
}
